from .serializer import UserInfoSerializer
# Create your views here.
from random import choice
from django.contrib.auth import get_user_model
from django.contrib.auth.backends import ModelBackend
from django.db.models import Q
from rest_framework import mixins
from rest_framework.views import APIView
from rest_framework import viewsets
from rest_framework.response import Response
from rest_framework import status
from utils.yunpian import Yunpian
from .serializer import UserRegisterSerialier,UserSummarySerializer
from .serializer import SmsSerializer,MessageSerializer,MessageDetailSerializer
from .models import VerifyCode,GradeStudent
from utils.permission import IsOwnerOrReadOnly,IsOwner
from rest_framework.permissions import IsAuthenticated
from rest_framework.authentication import SessionAuthentication
from rest_framework_jwt.authentication import JSONWebTokenAuthentication
from operation.serializer import UserScoreSerializers
import random
from operation.models import UserScore
from datetime import datetime
from datetime import timedelta
from MxOnline import settings
import requests
import json
from rest_framework_jwt.settings import api_settings
User = get_user_model()


class CustomBackend(ModelBackend):
    """
    自定义用户登陆认证
    """
    def authenticate(self, request, username=None, password=None, **kwargs):
        try:
            user = User.objects.get(Q(username=username)|Q(mobile=username)|Q(email=username))
            if user.check_password(password):
                return user
        except Exception as e:
            return None


def jwt_response_payload_handler(token, user=None, request=None):
    return {
        'token': token,
        'user': UserInfoSerializer(user, context={'request': request}).data
    }


class SmsCodeViewSet(mixins.CreateModelMixin,viewsets.GenericViewSet):
    """
    create:
    发送短信验证码
    """
    serializer_class = SmsSerializer

    def generate_code(self):
        seeds = "1234567890"
        random_str = []
        for i in range(4):
            random_str.append(choice(seeds))
        return "".join(random_str)

    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        mobile = serializer.validated_data["mobile"]
        y = Yunpian('fc076a5c49ff9ceb71ed')
        code = self.generate_code()
        res = y.send_sms(code, mobile)
        if str(res) != "1":
            return Response({
                "msg":"发送失败",
            },status=status.HTTP_404_NOT_FOUND)
        else :
            v = VerifyCode(mobile=mobile,code=code)
            v.save()
            return Response({
                "msg":"发送成功",
            },status=status.HTTP_201_CREATED)


class RegisterViewset(mixins.UpdateModelMixin,mixins.ListModelMixin,mixins.RetrieveModelMixin,mixins.CreateModelMixin,viewsets.GenericViewSet):
    """
    list:
    获取用户的摘要信息
    create:
    创建一个用户
    retrieve:
    获取一个用户的详细信息
    update:
    修改用户信息
    partial_update:
    部分更新
    """
    queryset = User.objects.all()
    authentication_classes = (JSONWebTokenAuthentication,SessionAuthentication)

    def get_serializer_class(self):
        if self.action == "create":
            return UserRegisterSerialier
        if self.action == "list":
            return UserSummarySerializer
        if self.action == "retrieve":
            return UserInfoSerializer
        return UserInfoSerializer

    def get_permissions(self):
        if self.action == "update":
            return [IsAuthenticated(),IsOwner()]
        if self.action == "retrieve":
            return [IsAuthenticated(),IsOwner()]
        return []

    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        self.perform_create(serializer)
        headers = self.get_success_headers(serializer.data)
        return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)


class MessageCountViewSet(mixins.ListModelMixin,viewsets.GenericViewSet):
    """
    list:
       获取我的考试数量，班级数量，未读消息数量
    """
    permission_classes = (IsOwner,IsAuthenticated)
    authentication_classes = (JSONWebTokenAuthentication,SessionAuthentication)

    def list(self, request, *args, **kwargs):
        from operation.models import SignUser,Sign
        sign_count = Sign.objects.filter(grade_id__in=self.request.user.grades.all().values_list("grade"),add_time__gte=datetime.now() - timedelta(minutes=10)).exclude(id__in=SignUser.objects.filter(students=self.request.user).values_list("sign")).count()
        g = request.user.grades.all()
        unread_msg = len(request.user.notifications.unread())
        my_class = len(g)
        grades = []
        for i in g:
            grades.extend(i.grade.course.all())
        exams = 0
        for i in grades:
            exams+=len(i.paperlist.filter().exclude(id__in=UserScore.objects.filter(user=request.user).values_list("paper")))
        data = {
            "unread_meg":unread_msg,
            "my_lass":my_class,
            "my_exam":exams,
            "sign_count":sign_count
        }
        return Response(data)


class MessageViewSet(mixins.ListModelMixin,mixins.RetrieveModelMixin,viewsets.GenericViewSet):
    """
    list:
    获取用户的消息
    retrieve:
    获取用户的某一条消息
    """

    def get_queryset(self):
        return self.request.user.notifications.all()

    def get_serializer_class(self):
        if self.action=="list":
            return MessageSerializer
        if self.action == "retrieve":
            return MessageDetailSerializer
        return MessageSerializer

    def retrieve(self, request, *args, **kwargs):
        instance = self.get_object()

        if instance.unread == True:
            instance.unread = False
            instance.save()
        serializer = self.get_serializer(instance)
        return Response(serializer.data)


class MyTimeTableViewSet(mixins.ListModelMixin,viewsets.GenericViewSet):
    """
    list:
    获取我的课程表(数据为固定数据)
    """
    def get_queryset(self):
        pass

    def list(self, request, *args, **kwargs):
        data = []
        random_list = ["数学","数学","数学","语文","语文","语文","英语","英语","英语","无课","体育"]
        weeks = ["周一","周二","周三","周四","周五"]
        courses_times = ["一节","二节","三节","四节"]
        for ji in courses_times:
            for week in weeks:
                data.append({"text":random.choice(random_list),"image":"favor","week":week,"js":ji})
        return Response(data)


class MyScoreViewSet(mixins.ListModelMixin,viewsets.GenericViewSet):
    permission_classes = (IsOwner,IsAuthenticated)
    authentication_classes = (JSONWebTokenAuthentication,SessionAuthentication)
    serializer_class = UserScoreSerializers

    def get_queryset(self):
        return UserScore.objects.filter(user=self.request.user)


class WechatLoginView(APIView):
    """
    微信登录逻辑
    """

    def post(self, request):
        # 前端发送code到后端,后端发送网络请求到微信服务器换取openid
        code = request.data.get('code')
        if not code:
            return Response({'message': '缺少code'}, status=status.HTTP_400_BAD_REQUEST)

        url = "https://api.weixin.qq.com/sns/jscode2session?appid={0}&secret={1}&js_code={2}&grant_type=authorization_code" \
            .format(settings.APP_ID, settings.APP_KEY, code)
        r = requests.get(url)
        res = json.loads(r.text)
        openid = res['openid'] if 'openid' in res else None
        if not openid:
            return Response({'message': '微信调用失败'}, status=status.HTTP_503_SERVICE_UNAVAILABLE)

        # 判断用户是否第一次登录
        try:
            user = User.objects.filter(openid=openid)[0]

        except Exception:
            # 微信用户第一次登陆,新建用户
            username = request.data.get('nickName',"111")
            avatarUrl = request.data.get('avatarUrl',"11111")
            user = User.objects.create(username=username,openid=openid,avator_url=avatarUrl)
            user.set_password(openid)

        # 手动签发jwt
        jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
        jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER

        payload = jwt_payload_handler(user)
        token = jwt_encode_handler(payload)

        resp_data = {
            "user":{
                "id": user.id,
                "username": user.username,
            },
            "token": token,
        }
        return Response(resp_data)
